package com.we823.project.controller.product;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jquery.jqgrid.model.JqGrid;
import com.we823.project.common.utils.CodeGenerate;
import com.we823.project.common.web.StockUtil;
import com.we823.project.common.web.status.PermissionStatus;
import com.we823.project.common.web.status.PlanStatus;
import com.we823.project.common.web.status.TaskStatus;
import com.we823.project.controller.AbstractBaseController;
import com.we823.project.core.web.WebConstants;
import com.we823.project.model.StationModel;
import com.we823.project.model.UserModel;
import com.we823.project.model.UserStationModel;
import com.we823.project.model.product.PlanDetailModel;
import com.we823.project.model.product.PlanModel;
import com.we823.project.model.product.ProductTaskModel;
import com.we823.project.model.repo.MaterialBomModel;
import com.we823.project.model.repo.MaterialModel;
import com.we823.project.model.repo.MaterialStockInModel;
import com.we823.project.model.repo.MaterialStockOutModel;
import com.we823.project.model.repo.StockInTaskModel;
import com.we823.project.model.repo.StockOutTaskModel;
import com.we823.project.repository.component.CalculateUtil;
import com.we823.project.repository.service.StationService;
import com.we823.project.repository.service.UserService;
import com.we823.project.repository.service.UserStationService;
import com.we823.project.repository.service.product.PlanDetailService;
import com.we823.project.repository.service.product.PlanService;
import com.we823.project.repository.service.product.ProductTaskService;
import com.we823.project.repository.service.repo.MaterialBomService;
import com.we823.project.repository.service.repo.MaterialService;
import com.we823.project.repository.service.repo.MaterialStockInService;
import com.we823.project.repository.service.repo.MaterialStockOutService;
import com.we823.project.repository.service.repo.MaterialStockService;
import com.we823.project.repository.service.repo.StockInTaskService;
import com.we823.project.repository.service.repo.StockOutTaskService;
import com.we823.project.repository.service.sys.CalculateService;
import com.we823.utils.web.DateUtil;
import com.we823.utils.web.RequestUtil;

@Controller
@RequestMapping(WebConstants.PRODUCT_PRODUCT_TASK)
public class ProductTaskController extends AbstractBaseController<ProductTaskModel>  {

	private ProductTaskService productTaskService;

	@Autowired
	public ProductTaskController(ProductTaskService productTaskService) {
		super(productTaskService);
		this.productTaskService=productTaskService;
		setResourceIdentity("product:product_task");
	}

	private Logger logger = LoggerFactory.getLogger(ProductTaskController.class);
	
	private String baseUrl = WebConstants.PRODUCT_PRODUCT_TASK_TEMPLATE;
	
	@Autowired
	private StationService stationService;
	@Autowired
	private UserService userService;
	@Autowired
	private UserStationService userStationService;
	@Autowired
	private PlanDetailService planDetailService;
	@Autowired
	private PlanService planService;
	
	@Autowired
	private CalculateService calculateService;
	@Autowired
	private CalculateUtil calculateUtil;
	@Autowired
	private MaterialStockOutService materialStockOutService;
	@Autowired
	private MaterialStockInService materialStockInService;

	private @Resource StockOutTaskService stockOutTaskService;

	private @Resource StockInTaskService stockInTaskService;
	@Autowired
	private MaterialStockService materialStockService;
	@Autowired
	private MaterialBomService materialBomService;

	@Autowired
	private MaterialService materialService;

	private Map<Integer, PlanModel> planMap;
	private Map<Integer, PlanDetailModel> planDetailMap;
	private Map<Integer, StationModel> stationMap;
	private Map<String, MaterialModel> materialMap = new HashMap<>();

	@RequestMapping("index")
	public String index(HttpServletRequest request, Model model) {
		check(PermissionStatus.VIEW);
		Calendar calendar = Calendar.getInstance();
		model.addAttribute("currentYear",calendar.get(Calendar.YEAR));
		model.addAttribute("currentMonth",calendar.get(Calendar.MONTH)+1);
		model.addAttribute("currentDay",calendar.get(Calendar.DATE));
		model.addAttribute("days",calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		return baseUrl + "index";
	}

	private int getUserId(HttpServletRequest request) {
		UserModel userModel = (UserModel) request.getSession().getAttribute(WebConstants.CURRENT_USER);
		if(userModel!=null) {
			return userModel.getId();
		}
		return 0;
	}

	@RequestMapping("getPlanDetails")
	@ResponseBody
	public Model getPlanDetails(HttpServletRequest request, Model model) {
		check(PermissionStatus.VIEW);
 		int userId = getUserId(request);
		List<UserStationModel> userStationModels = userStationService.findByUserId(userId);
		List<Integer> stationIds = getStationIds(userStationModels);
		if (userStationModels != null && userStationModels.size()>0) {
			// 未确认
			List<PlanDetailModel> noConfirmPlanDetails = planDetailService.findByStatusAndStationIdIn(TaskStatus.NoConfirm, stationIds);
			//fillPlanInfo(noConfirmPlanDetails);
			checkPreProcessStatus(noConfirmPlanDetails);
			model.addAttribute("planDetails", noConfirmPlanDetails);
			if (noConfirmPlanDetails != null && noConfirmPlanDetails.size() > 0) {
				model.addAttribute("hasContent", true);
				model.addAttribute("count", noConfirmPlanDetails.size());
			} else {
				model.addAttribute("noContent", true);
				model.addAttribute("count", 0);
			}
			model.addAttribute("hasError",false);
		}else {
			model.addAttribute("noContent",true);
			model.addAttribute("count",0);
			model.addAttribute("hasError",true);
			model.addAttribute("message","当前用户没有分配工位，无法获取计划任务！请通知管理员分配工位或去除工位权限");
		}
		return model;
	}

	/**
	 * 检查前导工序是否完成，只有前导工序完成，才能继续这道工序
	 * @param noConfirmPlanDetails
	 */
	private void checkPreProcessStatus(
			List<PlanDetailModel> noConfirmPlanDetails) {
		if (noConfirmPlanDetails!=null && noConfirmPlanDetails.size()>0) {
			for (PlanDetailModel planDetailModel : noConfirmPlanDetails) {
				String preProcess = planDetailModel.getPreProcess();
				if ("无".equals(preProcess)) {
					planDetailModel.setHasPreProcess(false);
				}else {
					int deep = planDetailModel.getDeep();
					int orderid = planDetailModel.getOrderid();
					int planId = planDetailModel.getPlanId();
					List<PlanDetailModel> prePlanDetailModels = null;
					if (orderid==1) {
						//当orderid为1时，说明前导工序为下一级BOM的工序
						deep = deep + 1;
					}
					List<String> preProcessList = Lists.newArrayList();
					if (!StringUtils.isEmpty(preProcess)) {
						String[] ss = StringUtils.split(preProcess, ",");
						preProcessList = Arrays.asList(ss);
					}
					//当orderid大于1时，有可能找到自身,需要增加小于orderid的判断，但会存在无法找到前导工序的情况，需要再次往下查找
					if (orderid>1) {
						prePlanDetailModels = planDetailService.findByPlanIdAndDeepAndProcessInAndOrderidLessThan(planId,deep,preProcessList,orderid);
					}else {
						prePlanDetailModels = planDetailService.findByPlanIdAndDeepAndProcessIn(planId,deep,preProcessList);
					}
					if (prePlanDetailModels!=null && prePlanDetailModels.size()>0) {
						List<String> needSearchNextDeepList = Lists.newArrayList();
						if (prePlanDetailModels.size()<preProcessList.size()) {
							List<String> existProcess = Lists.newArrayList();
							for (PlanDetailModel prePlanDetailModel : prePlanDetailModels) {
								existProcess.add(prePlanDetailModel.getProcess());
							}
							for (String tempProcess : preProcessList) {
								if (!existProcess.contains(tempProcess)) {
									needSearchNextDeepList.add(tempProcess);
								}
							}
						}
						if (needSearchNextDeepList.size()>0) {
							deep = deep + 1;
							List<PlanDetailModel> otherPrePlanDetailModels = planDetailService.findByPlanIdAndDeepAndProcessIn(planId, deep, needSearchNextDeepList);
							if (otherPrePlanDetailModels!=null && otherPrePlanDetailModels.size()>0) {
								prePlanDetailModels.addAll(otherPrePlanDetailModels);
							}
						}
					}
					if (prePlanDetailModels!=null && prePlanDetailModels.size()>0) {
						for (PlanDetailModel prePlanDetailModel : prePlanDetailModels) {
							TaskStatus taskStatus = prePlanDetailModel.getStatus();
							if (TaskStatus.Finished!=taskStatus) {
								planDetailModel.setHasPreProcess(true);
								planDetailModel.setProcessMessage(prePlanDetailModel.getProcess()+" 未完成");
								break;
							}
						}
					}
				}
			}
		}
	}

	@RequestMapping("getProductTasks")
	@ResponseBody
	public Model getProductTasks(HttpServletRequest request, Model model) {
		check(PermissionStatus.VIEW);
		String statusString = RequestUtil.getValueByParam(request, "status");
		int userId = getUserId(request);
		if (statusString != null) {
			TaskStatus status = TaskStatus.valueOf(statusString);
			if (status != null) {
				List<ProductTaskModel> productTaskModels = null;
				
				Sort sort = new Sort(Direction.ASC,"addtime");
				
				if(status.equals(TaskStatus.NoMaterial)){
					List<TaskStatus> statusList = new ArrayList<>();
					statusList.add(TaskStatus.NoMaterial);
					statusList.add(TaskStatus.ApplingMaterial);
					statusList.add(TaskStatus.ReturnMaterial);
					
					productTaskModels = productTaskService.findByUserIdAndStatusIn(userId,statusList,sort);
				}else if(status.equals(TaskStatus.Producting)){
					List<TaskStatus> statusList = new ArrayList<>();
					statusList.add(TaskStatus.ShortError);
					statusList.add(TaskStatus.Producting);
					productTaskModels = productTaskService.findByUserIdAndStatusIn(userId,statusList,sort);
				}else {
					productTaskModels = productTaskService.findByStatusAndUserId(status, userId,sort);
				}
				
				try {
					fillPlanDetails(productTaskModels);
				} catch (Exception e) {
					model.addAttribute("hasError",true);
					model.addAttribute("message",e.getMessage());
					model.addAttribute("noContent", true);
					model.addAttribute("count", 0);
					
					return model;
				}

				if (productTaskModels != null && productTaskModels.size() > 0) {
					model.addAttribute("hasContent", true);
					model.addAttribute("hasError",false);
					model.addAttribute("count", productTaskModels.size());
					model.addAttribute("productTasks", productTaskModels);
				} else {
					model.addAttribute("noContent", true);
					model.addAttribute("count", 0);
					model.addAttribute("hasError",false);
				}
			}
		}
		return model;
	}

	/**
	 * 工位确认任务单
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("confirm")
	@ResponseBody
	public Model confirmPlanDetail(HttpServletRequest request, Model model) {
		check(PermissionStatus.UPDATE);
		Integer id = RequestUtil.getValueByParam(request, "id", 0);
		
		int userId = getUserId(request);
		
		boolean hasError = false;
		String message = "";
		if (id == 0) {
			hasError = true;
			message = "计划详情id不正确，无法确认";
		} else {
			PlanDetailModel planDetailModel = planDetailService.findOne(id);
			if (planDetailModel == null) {
				hasError = true;
				message = "未找到计划详情,无法确认";
			} else {
				ProductTaskModel productTaskModel = new ProductTaskModel();
				productTaskModel.setName("任务单-" + planDetailModel.getId());
				productTaskModel.setCode("TASK-" + planDetailModel.getId());
				productTaskModel.setPlanDetailId(planDetailModel.getId());
				productTaskModel.setStatus(TaskStatus.NoMaterial);

				planDetailModel.setStatus(TaskStatus.NoMaterial);

				productTaskModel.setNeedTotal(planDetailModel.getNeedTotal());
				productTaskModel.setAddtime(new Date());

				// 获取session中的id
				productTaskModel.setUserId(userId);

				productTaskService.save(productTaskModel);
				planDetailService.update(planDetailModel);
			}
		}

		model.addAttribute("hasError", hasError);
		model.addAttribute("message", message);
		return model;
	}

	/**
	 * 5-16 加入taskIds，支持多个任务同时申请物料
	 * 申请物料，根据planDetail查询
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("applyMaterial")
	@ResponseBody
	public Model apply(HttpServletRequest request, Model model) {
		check(PermissionStatus.CREATE);
		Integer id = RequestUtil.getValueByParam(request, "id", 0);

		String taskIds = RequestUtil.getValueByParam(request, "taskIds");
		
		Set<Integer> taskIdSet = new HashSet<Integer>();
		taskIdSet.add(id);
		if (!StringUtils.isEmpty(taskIds)) {
			String[] taskIdArray = StringUtils.split(taskIds,',');
			if (taskIdArray!=null && taskIdArray.length>0) {
				for (String taskId : taskIdArray) {
					if (StringUtils.isNumeric(taskId)) {
						taskIdSet.add(Integer.parseInt(taskId));
					}
				}
			}
		}else {
			taskIds = id.toString();
		}
		boolean hasError = true;
		String message = "";
		int applyCount = 0;

		List<MaterialStockOutModel> materialStockOutModels = Lists.newArrayList();
		if(taskIdSet!=null & taskIdSet.size()>0) {
			for (Integer taskId : taskIdSet) {
				if (taskId > 0) {
					ProductTaskModel productTaskModel = productTaskService.findOne(taskId);
					if (productTaskModel != null) {
						try {
						   fillPlanDetail(productTaskModel);
						
						}catch(Exception ex) {
							model.addAttribute("hasError",true);
							model.addAttribute("message",ex.getMessage());
						}
						PlanDetailModel planDetailModel = productTaskModel.getPlanDetail();
						if (planDetailModel != null) {
							String materialCode = planDetailModel.getMaterialCode();
							
							List<MaterialBomModel> materialBomModels = materialBomService.findByProcessAndCode(planDetailModel.getProcess(), materialCode);

							if (materialBomModels != null && materialBomModels.size()>0) {
								List<MaterialStockOutModel> subMaterialStockOutModels = calculateUtil.getByBom(materialBomModels,materialCode,planDetailModel.getNeedTotal());
								if (subMaterialStockOutModels!=null && subMaterialStockOutModels.size()>0) {
									for (MaterialStockOutModel materialStockOutModel : subMaterialStockOutModels) {
										materialStockOutModel.setProductTask(productTaskModel);
									}
								}
								materialStockOutModels.addAll(subMaterialStockOutModels);
								
								hasError = false;
							}else{
								message += String.format("材料编号[%s]未找到BOM信息，请确认！",materialCode);
								hasError = true;
							}
						}
					}
				} else {
					message += "无法找到计划"+taskId+"详情；";
					hasError= true;
				}
			}
			if (materialStockOutModels.size()>0) {
				model.addAttribute("materialStockOuts", materialStockOutModels);
				hasError = false;
				applyCount = materialStockOutModels.size();
				
			}
		}else {
			message = "无法找到计划详情";
		}
		
		model.addAttribute("applyCount", applyCount);
		model.addAttribute("hasError", hasError);
		model.addAttribute("message", message);
		return model;
	}

	/**
	 *5-16 修改为同时申请多个任务的申请
	 * 提交物料申请信息
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("submitApply")
	@ResponseBody
	public Model submitApply(HttpServletRequest request, Model model) {
		check(PermissionStatus.CREATE);
		int applyCount = RequestUtil.getValueByParam(request, "apply_count", 0);
		int taskId = RequestUtil.getValueByParam(request, "task_id", 0);

		String taskIds = RequestUtil.getValueByParam(request, "taskIds");
		Set<Integer> taskIdSet = new HashSet<Integer>();
		if (!StringUtils.isEmpty(taskIds)) {
			String[] taskIdArray = StringUtils.split(taskIds,",");
			if (taskIdArray!=null && taskIdArray.length>0) {
				for (String sTaskId : taskIdArray) {
					if (StringUtils.isNumeric(sTaskId)) {
						taskIdSet.add(Integer.parseInt(sTaskId));
					}
				}
			}
		}
		
		/**
		 * 判断当前的任务号是否已经申请物料
		 */
		if (taskIdSet!=null && taskIdSet.size()>0) {
			for (Integer tempTaskId : taskIdSet) {
				boolean submited = checkSubmited(tempTaskId);
				if (submited) {
					model.addAttribute("hasError",true);
					model.addAttribute("message","任务单"+tempTaskId+"已经提交，无法再申请");
					logger.debug("{} submited!",tempTaskId);
					
					return model;
				}
			}
		}
		
		int userId = getUserId(request);
		
		String message = "";
		boolean hasError = true;
		List<MaterialStockOutModel> materialStockOutModels = Lists.newArrayList();
		int innerCount = 0; //内部流转的数量，若全部为内部流转，则直接更改为生产
		if (applyCount > 0) {
			ProductTaskModel productTaskModel = productTaskService.findOne(taskId);
			try {
				fillPlanDetail(productTaskModel);
			} catch (Exception e1) {
				model.addAttribute("hasError",true);
				model.addAttribute("message","提交物料申请失败，原因："+e1.getMessage());
				
				return model;
			}
			
			Map<Integer, ProductTaskModel> taskMap = productTaskService.mapByIds(taskIdSet);
			if (taskMap!=null && taskMap.size()>0) {
				
				List<ProductTaskModel> productTaskModels = Lists.newArrayList(taskMap.values().iterator());
				
				try {
					fillPlanDetails(productTaskModels);
				} catch (Exception e) {
					model.addAttribute("hasError",true);
					model.addAttribute("message","提交物料申请失败，原因："+e.getMessage());
					
					return model;
				}
			}
			
			for (int index = 0; index < applyCount; index++) {
				String materialCode = RequestUtil.getValueByParam(request, "material_code_" + index);
				float needNum = RequestUtil.getValueByParam(request, "needNum_" + index, 0f);
				String memo = RequestUtil.getValueByParam(request, "memo_" + index);
				String finalUnit = RequestUtil.getValueByParam(request, "finalUnit_"+index);
				int currentTaskId = RequestUtil.getValueByParam(request, "taskId_"+index, 0);

				MaterialStockOutModel materialStockOutModel = new MaterialStockOutModel();
				materialStockOutModel.setMaterialCode(materialCode);
				materialStockOutModel.setNeedNum(needNum);
				materialStockOutModel.setMemo(memo);
				//若物料号以R开头的为内部流动
				int flag = (materialCode.startsWith("R.")) ? 2 : 0;
				materialStockOutModel.setFlag(flag);
				if (flag==2) {
					materialStockOutModel.setFinalNum(needNum);
					innerCount++;
				}
				materialStockOutModel.setUserId(userId);
				materialStockOutModel.setCode(CodeGenerate.getMaterialStockOutCode());
				materialStockOutModel.setAddtime(new Date());
				materialStockOutModel.setRepoId(1);
				
				StringBuilder purposeBuilder = new StringBuilder();
				ProductTaskModel currentTask = null;
				if (currentTaskId>0) {
					if (taskMap!=null) {
						currentTask = taskMap.get(currentTaskId);
					}
				}
				try {
					if (currentTask!=null) {
						purposeBuilder.append("计划号：").append(currentTask.getPlanDetail().getPlanCode());
						purposeBuilder.append(" ").append(currentTask.getPlanDetail().getMemo());
					}
					
				}catch(Exception e) {
					
				}
				purposeBuilder.append(" 原材料出货");
				
				materialStockOutModel.setProductTask(currentTask);
				materialStockOutModel.setPurpose(purposeBuilder.toString());
				materialStockOutModel.setFinalUnit(finalUnit);
				
				UserModel userModel = getUserModel(request);
				String inputer = "未知";
				if(userModel!=null) {
					inputer = userModel.getRealname();
				}
				// 需要填入用户信息
				materialStockOutModel.setInputer(inputer);

				materialStockOutModels.add(materialStockOutModel);
			}
		}

		if (materialStockOutModels != null) {
			List<StockOutTaskModel> stockOutTaskModels = new ArrayList<>();
			for (MaterialStockOutModel materialStockOutModel : materialStockOutModels) {
				StockOutTaskModel stockOutCardModel = new StockOutTaskModel();
				materialStockOutService.save(materialStockOutModel);
				ProductTaskModel tempTaskModel = materialStockOutModel.getProductTask();
				int tempTaskId = 0;
				if (tempTaskModel!=null) {
					tempTaskId = tempTaskModel.getId();
				}
				stockOutCardModel.setTaskId(tempTaskId);
				stockOutCardModel.setStockOutId(materialStockOutModel.getId());
				stockOutCardModel.setAddtime(new Date());

				stockOutTaskModels.add(stockOutCardModel);
			}

			if (stockOutTaskModels.size() > 0) {
				for (StockOutTaskModel stockOutTaskModel : stockOutTaskModels) {
					stockOutTaskService.save(stockOutTaskModel);
				}
			}
			hasError = false;
			if (taskIdSet!=null && taskIdSet.size()>0) {
				for (Integer needChangeStatusTaskId : taskIdSet) {
					try {
						if (applyCount>innerCount) {
							logger.debug("applyCount>innerCount:{}","进入等待申请中。。。。");
							changeStatus(needChangeStatusTaskId, TaskStatus.ApplingMaterial);
						}else {
							logger.debug("applyCount<=innerCount:{}","直接进入未生产状态。。。。");
							changeStatus(needChangeStatusTaskId, TaskStatus.NoProduct);
						}
						
					} catch (Exception e) {
						hasError = true;
						message = e.getMessage();
					}
				}
			}
			
		}
		model.addAttribute("hasError", hasError);
		model.addAttribute("message", message);
		return model;
	}

	/**
	 * 判断此taskId是否已经提交
	 * @param taskId
	 * @return
	 */
	private boolean checkSubmited(int taskId) {
		List<StockOutTaskModel> stockOutTaskModels = stockOutTaskService.findByTaskId(taskId);
		if (stockOutTaskModels!=null && stockOutTaskModels.size()>0) {
			return true;
		}
		return false;
	}

	@RequestMapping("getOne")
	@ResponseBody
	public Model getOne(HttpServletRequest request,Model model) {
		int id = RequestUtil.getValueByParam(request, "id", 0);
		if (id>0) {
			ProductTaskModel productTaskModel = productTaskService.findOne(id);
			try {
				fillPlanDetail(productTaskModel);
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("无法获取记录，原因："+e.getMessage());
				
				return model;
			}
			model.addAttribute("productTask",productTaskModel);
			model.addAttribute("hasError",false);
		}else {
			model.addAttribute("hasError",true);
			model.addAttribute("message","找不到记录！");
		}
		return model;
	}
	private UserModel getUserModel(HttpServletRequest request) {
		return (UserModel) request.getSession().getAttribute(WebConstants.CURRENT_USER);
	}

	
	/**
	 * 查看出库信息
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("showStockOuts")
	@ResponseBody
	public Model showStockOuts(HttpServletRequest request,Model model){
		check(PermissionStatus.VIEW);
		Integer cardId = RequestUtil.getValueByParam(request, "id", 0);
		if(cardId>0){
			List<StockOutTaskModel> stockOutCardModels = stockOutTaskService.findByTaskId(cardId);
			
			List<Integer> stockOutIdList = new ArrayList<>();
			if(stockOutCardModels!=null){
				for (StockOutTaskModel stockOutCardModel : stockOutCardModels) {
					stockOutIdList.add(stockOutCardModel.getStockOutId());
				}
			}
			List<MaterialStockOutModel> materialStockOutModels = materialStockOutService.findByIdIn(stockOutIdList);
			fillMaterial(materialStockOutModels);
			model.addAttribute("materialStockOuts",materialStockOutModels);
		}
		return model;
	}
	
	/**
	 * 确认物料申请
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("confirmApply")
	@ResponseBody
	public Model confirmApply(HttpServletRequest request,Model model){
		check(PermissionStatus.UPDATE);
		Integer cardId = RequestUtil.getValueByParam(request, "cardId", 0);
		
		String message = "";
		boolean hasError = true;
		if(cardId>0){
			try {
				changeStatus(cardId, TaskStatus.NoProduct);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			hasError = false;
			
            List<StockOutTaskModel> stockOutCardModels = stockOutTaskService.findByTaskId(cardId);
			
			List<Integer> stockOutIdList = new ArrayList<>();
			if(stockOutCardModels!=null){
				for (StockOutTaskModel stockOutCardModel : stockOutCardModels) {
					stockOutIdList.add(stockOutCardModel.getStockOutId());
				}
			}
			List<MaterialStockOutModel> materialStockOutModels = materialStockOutService.findByIdIn(stockOutIdList);
			if (materialStockOutModels!=null && materialStockOutModels.size()>0) {
				for (MaterialStockOutModel materialStockOutModel : materialStockOutModels) {
					String memo = RequestUtil.getValueByParam(request, "memo_"+materialStockOutModel.getId());
					materialStockOutModel.setMemo(memo);
				}
				
				materialStockOutService.save(materialStockOutModels);
			}
		}
		model.addAttribute("message",message);
		model.addAttribute("hasError",hasError);
		
		return model;
	}
	
	/**
	 * 修改task的状态
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping("changeStatus")
	@ResponseBody
	public Model changeStatus(HttpServletRequest request,Model model){
		check(PermissionStatus.UPDATE);
		Integer taskId = RequestUtil.getValueByParam(request, "id", 0);
		String statuString = RequestUtil.getValueByParam(request, "status");
		TaskStatus status = null;
		try{
			status = TaskStatus.valueOf(statuString);
		}catch(Exception ex){
			status = null;
		}
		
		String message = "";
		boolean hasError = true;
		if(taskId>0 && status!=null){
			try {
				changeStatus(taskId, status);
				hasError = false;
			} catch (Exception e) {
				hasError = true;
				message = e.getMessage();
			}
			
		}
		model.addAttribute(message);
		model.addAttribute(hasError);
		return model;
	}
	
	/**
	 * 修改plan\planDetail\productTask相关的状态信息
	 * @param taskId
	 * @param taskStatus
	 */
	private void changeStatus(Integer taskId, TaskStatus taskStatus) throws Exception{
		if (taskId > 0) {
			ProductTaskModel productTaskModel = productTaskService.findOne(taskId);
			if (productTaskModel != null) {
				fillPlanDetail(productTaskModel);
				try {
					
					PlanDetailModel planDetailModel = productTaskModel.getPlanDetail();
					if (planDetailModel!=null) {
						productTaskModel.setStatus(taskStatus);
						productTaskModel.getPlanDetail().setStatus(taskStatus);
						
						productTaskModel.setEdittime(new Date());
						
						
						//当确定完成时，需要判断是否相关计划的所有详细计划都完成，若完成了，则需要更改计划为完成
						/**
						 * 当生产的产品为中间产品时，内部流通，直接将信息通过仓库信息处理
						 * 当产品为最终产品时，需将产品交给任务管理员检验后再入库
						 */
						if(TaskStatus.Finished.equals(taskStatus)){
							productTaskModel.setFinishtime(new Date());
							productTaskModel.setFinalTotal(productTaskModel.getNeedTotal());
							
							String nextProcess = planDetailModel.getNextProcess();
							//如果没有后续计划，则为最终产品，不直接入库
							if ("无".equals(nextProcess)) {
								changePlanStatus(planDetailModel,PlanStatus.ProductFinish);
							}else {
								changePlanStatus(productTaskModel.getPlanDetail());
								stockIn(productTaskModel);
							}
						}

						
						if(TaskStatus.Producting.equals(taskStatus)){
							productTaskModel.setStarttime(new Date());
						}
						
						productTaskService.update(productTaskModel);
						planDetailService.update(productTaskModel.getPlanDetail());
						
						
						
					}else {
						logger.error("任务单中的计划详情为空，无法完成状态修改");
						throw new Exception("任务单中的计划详情为空，无法完成状态修改");
					}
					
				} catch (Exception ex) {
					logger.error(ex.getMessage());
					throw new Exception("修改计划状态发生错误："+ex.getMessage());
				}

			}
		}
	}

	/**
	 * 入库
	 * @param productTaskModel
	 */
	private void stockIn(ProductTaskModel productTaskModel) {
		if(productTaskModel!=null){
			MaterialStockInModel materialStockInModel = new MaterialStockInModel();
			materialStockInModel.setCode(CodeGenerate.getMaterialStockInCode());
			
			String materialCode = null;
			String unit = "";
			
			String checkstatus = "未确认";
			String memo = "工位生产完成入库";
			
			PlanDetailModel planDetailModel = productTaskModel.getPlanDetail();
			if(planDetailModel!=null){
				materialCode = planDetailModel.getMaterialCode();
				if(materialCode!=null){
					MaterialModel materialModel = materialService.findByCode(materialCode);
					if(materialModel!=null){
						unit = materialModel.getUnit();
					}
				}
				
				if (StringUtils.isEmpty(planDetailModel.getNextProcess())) {
					checkstatus = "未确认";
					if(planDetailModel!=null) {
						memo = String.format("计划单：%s 任务单：%s 工位：%s生产完成入库", planDetailModel.getPlanCode(),productTaskModel.getCode(),planDetailModel.getStationName());
					}
				}else {
					checkstatus = "内部流通无需确认";
					if(planDetailModel!=null) {
						memo = String.format("计划单：%s 任务单：%s 工位：%s生产完成入库", planDetailModel.getPlanCode(),productTaskModel.getCode(),planDetailModel.getStationName());
					}
					
				}
			}
			materialStockInModel.setMaterialCode(materialCode);
			materialStockInModel.setTotalNum(productTaskModel.getFinalTotal());
			UserModel userModel =(UserModel) SecurityUtils.getSubject().getSession().getAttribute(WebConstants.CURRENT_USER);
			if (userModel!=null) {
				materialStockInModel.setInputer(userModel.getRealname());
			}
			
			materialStockInModel.setAddtime(new Date());
			materialStockInModel.setMemo(memo);
			materialStockInModel.setUnit(unit);
			

			materialStockInModel.setCheckstatus(checkstatus);
			
			
			materialStockInModel = materialStockInService.save(materialStockInModel);
			
			StockInTaskModel stockInTaskModel = new StockInTaskModel();
			stockInTaskModel.setAddtime(new Date());
			stockInTaskModel.setTaskId(productTaskModel.getId());
			stockInTaskModel.setStockInId(materialStockInModel.getId());
			
			stockInTaskService.save(stockInTaskModel);
			
			//产品入库时，修改了stockIn,同时应修改stock库
			StockUtil.changeStock(materialStockInModel, materialStockService);
		}
		
	}

	
	
	/**
	 * 修改计划的状态为生产完成，需要检验并入库
	 * @param planDetailModel
	 * @param productfinish
	 */
	private void changePlanStatus(PlanDetailModel planDetailModel,
			PlanStatus productfinish) {
		int planId = planDetailModel.getPlanId();
		if (planId>0) {
			PlanModel planModel = planService.findOne(planId);
			if (planModel!=null) {
				planModel.setStatus(productfinish);
				planModel.setEdittime(new Date());
				planService.update(planModel);
			}
		}
		
	}
	
	private void changePlanStatus(PlanDetailModel planDetailModel) {
		if(planDetailModel!=null){
			int planId = planDetailModel.getPlanId();
			if(planId>0){
				List<PlanDetailModel> planDetailModels = planDetailService.findByPlanId(planId);
				boolean finished = true;
				if(planDetailModels!=null && planDetailModels.size()>0){
					for (PlanDetailModel tempPlanDetailModel : planDetailModels) {
						if(!TaskStatus.Finished.equals(tempPlanDetailModel.getStatus())){
							finished = false;
							break;
						}
					}
				}
				if(finished){
					PlanModel planModel = planService.findOne(planId);
					if(planModel!=null){
						planModel.setStatus(PlanStatus.Finish);
						planModel.setEdittime(new Date());
						planService.update(planModel);
					}
				}
			}
		}
		
	}

	
	@RequestMapping("listEx")
	public String listEx(HttpServletRequest request,Model model) {
		int currentYear = DateUtil.getYear();
		int currentMonth = DateUtil.getMonth();
		int currentDay = DateUtil.getDay();
		
		int days = DateUtil.getMaxDay(currentYear, currentMonth);
		model.addAttribute("currentYear",currentYear);
		model.addAttribute("currentMonth",currentMonth);
		model.addAttribute("currentDay",currentDay);
		
		model.addAttribute("days",days);
		
		return baseUrl + "list";
	}
	
	@RequestMapping("getFinished")
	@ResponseBody
	public Model getFinished(HttpServletRequest request,Model model) {
		int year = RequestUtil.getValueByParam(request, "year", 0);
		int month = RequestUtil.getValueByParam(request, "month", 0);
		int day = RequestUtil.getValueByParam(request, "day", 0);
		
		int userId = getUserId(request);
		TaskStatus taskStatus = TaskStatus.Finished;
		
		JqGrid<ProductTaskModel> jqGrid = new JqGrid<ProductTaskModel>(request,model);
		
		PageRequest pageRequest = getPageRequest(jqGrid, request);
		
		Page<ProductTaskModel> productTaskPage = productTaskService.findByStatusAndUserIdAndDate(taskStatus, userId, year, month,day,pageRequest);
		if (productTaskPage!=null) {
			List<ProductTaskModel> productTaskModels = productTaskPage.getContent();
			if (productTaskModels!=null) {
				try {
					fillPlanDetails(productTaskModels);
				} catch (Exception e) {
					
				}
			}
			jqGrid.setDatarows(productTaskModels);
			jqGrid.setRecords(productTaskPage.getTotalElements());
		}
		jqGrid.flush();
		return model;
	}
	
	@Override
	protected Sort getSort(HttpServletRequest request) {
		Sort sort = super.getSort(request);
		if (sort==null) {
			sort = new Sort(Direction.DESC,"finishtime");
		}
		return sort;
	}
	private void fillMaterial(List<MaterialStockOutModel> materialStockOutModels) {
		if(materialStockOutModels!=null && materialStockOutModels.size()>0){
			List<String> materialCodeList = new ArrayList<>();
			for (MaterialStockOutModel materialStockOutModel : materialStockOutModels) {
				String materialCode = materialStockOutModel.getMaterialCode();
				materialCodeList.add(materialCode);
			}
			if(materialCodeList!=null){
				List<MaterialModel> materialModels = materialService.findByCodeIn(materialCodeList);
				for (MaterialModel materialModel : materialModels) {
					materialMap.put(materialModel.getCode(), materialModel);
				}
			}
			
			for (MaterialStockOutModel materialStockOutModel : materialStockOutModels) {
				MaterialModel materialModel = materialMap.get(materialStockOutModel.getMaterialCode());
				materialStockOutModel.setMaterial(materialModel);
				if (StringUtils.isEmpty(materialStockOutModel.getFinalUnit())) {
					if (materialModel!=null) {
						materialStockOutModel.setFinalUnit(materialModel.getUnit());
					}
				}
			}
		}
		
	}

	private void fillPlanInfo(PlanDetailModel planDetailModel) throws Exception {
		if (planDetailModel != null) {
			if (planMap == null) {
				planMap = Maps.newHashMap();
			}
			int planId = planDetailModel.getPlanId();
			if (!planMap.containsKey(planId)) {
				PlanModel planModel = planService.findOne(planId);
				planMap.put(planId, planModel);
			}
			if (planMap.containsKey(planId)) {
				planDetailModel.setPlan(planMap.get(planId));
			}else {
				throw new Exception("无法找到该计划详情："+planDetailModel.getId()+" 所属的计划:"+planId);
			}
			
			int stationId = planDetailModel.getStationId();
			if (stationId>0) {
				if (stationMap==null) {
					stationMap = stationService.map();
				}
				StationModel stationModel = stationMap.get(stationId);
				if (stationModel!=null) {
					planDetailModel.setStation(stationModel);
					planDetailModel.setStationName(stationModel.getName());
				}else {
					throw new Exception("无法找到该计划详情："+planDetailModel.getId()+" 确认的工位信息："+planDetailModel.getStationId());
				}
			}
		}
	}

	private void fillPlanDetails(List<ProductTaskModel> productTaskModels) throws Exception {
		if (productTaskModels != null && productTaskModels.size() > 0) {
			Map<String, MaterialModel> materialMap = materialService.map();
			for (ProductTaskModel productTaskModel : productTaskModels) {
				try {
					fillPlanDetail(productTaskModel);
				} catch (Exception e) {
					throw new Exception(e.getMessage());
				}
				PlanDetailModel planDetailModel = productTaskModel.getPlanDetail();
				if(planDetailModel!=null) {
					MaterialModel materialModel = materialMap.get(planDetailModel.getMaterialCode());
					productTaskModel.setCardname(materialModel.getCardname());
				}
			}
		}
	}

	/**
	 * 
	 * @param productTaskModel
	 * @throws Exception 
	 */
	private void fillPlanDetail(ProductTaskModel productTaskModel) throws Exception {
		if (productTaskModel != null) {
			if (planDetailMap == null) {
				planDetailMap = Maps.newHashMap();
			}
			int planDetailId = productTaskModel.getPlanDetailId();
			if (!planDetailMap.containsKey(planDetailId)) {
				PlanDetailModel planDetailModel = planDetailService.findOne(planDetailId);
				if (planDetailModel==null) {
					throw new Exception("无法找到该任务单："+productTaskModel.getId()+" 对应的计划详情："+planDetailId);
				}
				try {
				    fillPlanInfo(planDetailModel);
				}catch(Exception ex) {
					throw new Exception(ex.getMessage());
				}
				productTaskModel.setPlanDetail(planDetailModel);
			}
		}
	}


	private List<Integer> getStationIds(List<UserStationModel> userStationModels) {
		List<Integer> stationIds = new ArrayList<>();
		if (userStationModels != null) {
			for (UserStationModel userStationModel : userStationModels) {
				stationIds.add(userStationModel.getStationId());
			}
		}
		return stationIds;
	}

	public StationService getStationService() {
		return stationService;
	}

	public void setStationService(StationService stationService) {
		this.stationService = stationService;
	}

	public UserService getUserService() {
		return userService;
	}

	public void setUserService(UserService userService) {
		this.userService = userService;
	}

	public UserStationService getUserStationService() {
		return userStationService;
	}

	public void setUserStationService(UserStationService userStationService) {
		this.userStationService = userStationService;
	}

	public PlanDetailService getPlanDetailService() {
		return planDetailService;
	}

	public void setPlanDetailService(PlanDetailService planDetailService) {
		this.planDetailService = planDetailService;
	}

	public PlanService getPlanService() {
		return planService;
	}

	public void setPlanService(PlanService planService) {
		this.planService = planService;
	}

	public ProductTaskService getProcessCardService() {
		return productTaskService;
	}

	public void setProcessCardService(ProductTaskService processCardService) {
		this.productTaskService = processCardService;
	}

	public CalculateService getCalculateService() {
		return calculateService;
	}

	public void setCalculateService(CalculateService calculateService) {
		this.calculateService = calculateService;
	}

	public CalculateUtil getCalculateUtil() {
		return calculateUtil;
	}

	public void setCalculateUtil(CalculateUtil calculateUtil) {
		this.calculateUtil = calculateUtil;
	}

	public MaterialStockOutService getMaterialStockOutService() {
		return materialStockOutService;
	}

	public void setMaterialStockOutService(MaterialStockOutService materialStockOutService) {
		this.materialStockOutService = materialStockOutService;
	}

	public MaterialService getMaterialService() {
		return materialService;
	}

	public void setMaterialService(MaterialService materialService) {
		this.materialService = materialService;
	}

	public MaterialStockInService getMaterialStockInService() {
		return materialStockInService;
	}

	public void setMaterialStockInService(MaterialStockInService materialStockInService) {
		this.materialStockInService = materialStockInService;
	}

	public StockInTaskService getStockInTaskService() {
		return stockInTaskService;
	}

	public void setStockInTaskService(StockInTaskService stockInTaskService) {
		this.stockInTaskService = stockInTaskService;
	}

	public MaterialStockService getMaterialStockService() {
		return materialStockService;
	}

	public void setMaterialStockService(MaterialStockService materialStockService) {
		this.materialStockService = materialStockService;
	}

	@Override
	public Page<ProductTaskModel> getData(PageRequest pageRequest,
			HttpServletRequest request, Model model, boolean pageable) {
		
		return null;
	}

	public MaterialBomService getMaterialBomService() {
		return materialBomService;
	}

	public void setMaterialBomService(MaterialBomService materialBomService) {
		this.materialBomService = materialBomService;
	}

}
